home *** CD-ROM | disk | FTP | other *** search
/ System Booster / System Booster.iso / Texteditors / Origami / Sources / src / origami / scrbuff.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-09-27  |  30.4 KB  |  1,207 lines

  1. /*{{{}}}*/
  2. /*{{{  includes*/
  3. #ifdef CONFIG_H
  4. #   include "config.h"
  5. #endif
  6.  
  7. #include <stdlib.h>
  8. #include <stdio.h>
  9. #include <sys/types.h>
  10. #include <ctype.h>
  11. #include <unistd.h>
  12. #include <string.h>
  13. #include <limits.h>
  14.  
  15. #define I_DISPLAY_C
  16. #define I_GETTK_C
  17. #define I_MAIN_C
  18. #define I_SCREEN_C
  19. #define I_SIGNALS_C
  20. #define SCRBUFF_C
  21.  
  22. #include "origami.h"
  23. #include <lib/ori_add_lib.h>
  24. #include <h/envvar_str.h>
  25. /*}}}  */
  26.  
  27. /*{{{  types*/
  28. /*{{{  pentype*/
  29. #define PEN_MASK (~(O_NOP-1))
  30. typedef enum { NORM=0,HIGHLIGHT=O_NOP,SG_SPACE=PEN_MASK } pentype;
  31. /*}}}  */
  32. /*{{{  c_p_type - coding pen and character*/
  33. #define c_p_code_gen(c,p) ((c)|(p))
  34.  
  35. typedef enum
  36.  { SPACE_CODE=c_p_code_gen(' ',NORM),
  37.    SO_CODE   =c_p_code_gen('@',SG_SPACE),
  38.    SE_CODE   =c_p_code_gen('$',SG_SPACE)
  39.  } c_p_code;
  40.  
  41. #define B_code_c_p(c,p) ((c_p_code)c_p_code_gen(c,p))
  42. #define B_get_pen(c)    ((c)&PEN_MASK)
  43. #define B_get_char(c)   ((c)&(~(PEN_MASK)))
  44. #define B_test_pen(c,p) (B_get_pen(c)==(p))
  45. /*}}}  */
  46. /*{{{  chg_type - how is a line changed*/
  47. typedef enum { OK=0,CHANGED,INVALID } chg_type;
  48. /*}}}  */
  49.  
  50. typedef struct
  51.  { c_p_code *code;  /* char and pen data */
  52.    chg_type mode; /* changed? */
  53.    int id;          /* line number on old screen */
  54.  } linebuffer;
  55. /*}}}  */
  56. /*{{{  variables*/
  57. private linebuffer *B_scr_data=0;   /* malloced space for 2 buffers */
  58.  
  59. private boolean B_buf_id;           /* tag for current of 2 buffers */
  60. private linebuffer *B_current_scr=0;/* Pointer to current screen buffer */
  61.  
  62. private c_p_code *B_empty_line;     /* screen.w sized array with SPACE_CODE */
  63. private c_p_code *B_buff_line;      /* screen.w sized array */
  64.  
  65. private linebuffer *B_cur_line;     /* pointer to current line in buffer */
  66.  
  67. private win_data B_pos={0,0};       /* buffer cursor */
  68. private pentype B_pen;              /* current pen */
  69.  
  70. private boolean B_clr_scr_used=True;/* should ClrScr used first on flush */
  71. private int B_new_line;             /* no of deleted/scrolled out lines */
  72. private boolean B_use_dl_al;        /* should next flush use il/al */
  73. private chg_type B_scr_mode;        /* do a full redraw at next flush */
  74. private boolean B_check_so_glitch;  /* any standout glitch to be handled */
  75.  
  76. private boolean B_do_buffer=False;  /* is terminal initialised */
  77. private boolean B_active=False;     /* buffered termout active */
  78. /*}}}  */
  79.  
  80. /*{{{  screen handling*/
  81. private win_data scr_pos={ 0,0 };
  82. /*{{{  S_invalid_pos*/
  83. #define S_invalid_pos() (scr_pos.h=0)
  84. /*}}}  */
  85. /*{{{  S_shift_pos*/
  86. #define S_shift_pos(x) \
  87.   do { if ((scr_pos.w+=x)>screen.w) S_invalid_pos(); } while (NEVER)
  88. /*}}}  */
  89. /*{{{  S_step_or_move*/
  90. private void S_step_or_move(int y,int x)
  91. {
  92.   if (scr_pos.h==0)
  93.      move_cursor_to(y,x);
  94.   else if (scr_pos.h!=y || scr_pos.w!=x)
  95.      step_or_move_cursor(y,x,y-scr_pos.h,x-scr_pos.w);
  96.   else
  97.      return;
  98.   scr_pos.h=y;
  99.   scr_pos.w=x;
  100. }
  101. /*}}}  */
  102. /*{{{  S_moveclreol*/
  103. #define S_moveclreol(y,x) (moveclreol((y),(x)),S_invalid_pos())
  104. /*}}}  */
  105. /*{{{  S_ClrScr*/
  106. #define S_ClrScr() (ClrScr(),S_invalid_pos())
  107. /*}}}  */
  108. /*}}}  */
  109. /*{{{  internal buffer handling procedures*/
  110. /*{{{  B_check_active*/
  111. #define B_check_active() (redraw_on_sig=!(B_active=B_do_buffer&&B_scr_data))
  112. /*}}}  */
  113.  
  114. /*{{{  B_get_start*/
  115. #define B_get_start(i) (B_current_scr=B_scr_data-1+((i)?screen.h:0))
  116. /*}}}  */
  117. /*{{{  B_toggle_start*/
  118. #define B_toggle_start() B_get_start(B_buf_id= !B_buf_id)
  119. /*}}}  */
  120.  
  121. /*{{{  B_check_h_position*/
  122. #define B_check_h_pos(ph) \
  123.    do{if((ph)<=0)(ph)=1;else if((ph)>screen.h)(ph)=screen.h;}while(NEVER)
  124. /*}}}  */
  125. /*{{{  B_check_high_w_position*/
  126. #define B_check_high_w_pos(pw) \
  127.    do{if((pw)>screen.w)(pw)=screen.w;}while(NEVER)
  128. /*}}}  */
  129. /*{{{  B_check_w_position*/
  130. #define B_check_w_pos(pw) \
  131.    do{if((pw)<=0)(pw)=1;else B_check_high_w_pos(pw);}while(NEVER)
  132. /*}}}  */
  133. /*{{{  B_check_position*/
  134. #define B_check_pos(ph,pw) \
  135.    do{B_check_h_pos(ph);B_check_w_pos(pw);}while(NEVER)
  136. /*}}}  */
  137. /*{{{  B_inc_w_position*/
  138. #define B_inc_w_position(p) do{if(++(p)>screen.w)(p)=screen.w;}while(NEVER)
  139. /*}}}  */
  140. /*{{{  B_update_line_pointer*/
  141. #define B_update_line_pointer() (B_cur_line=B_current_scr+B_pos.h)
  142. /*}}}  */
  143.  
  144. /*{{{  B_check_cursor*/
  145. private void B_check_cursor(void)
  146. {
  147.   B_check_pos(B_pos.h,B_pos.w);
  148.   B_update_line_pointer();
  149. }
  150. /*}}}  */
  151.  
  152. /*{{{  B_copy*/
  153. #define B_copy(d,s,l) memcpy((d),(s),(l)*sizeof(c_p_code))
  154. /*}}}  */
  155. /*{{{  B_cmp*/
  156. #define B_cmp(s1,s2,l) memcmp((s1),(s2),(l)*sizeof(c_p_code))
  157. /*}}}  */
  158. /*{{{  B_clr*/
  159. #define B_clr(l,f,t) B_copy((l)+(f),B_empty_line,(t)-(f)+1)
  160. /*}}}  */
  161.  
  162. /*{{{  B_al_dl_rotate*/
  163. private void B_al_dl_rotate(int from,int to)
  164. {
  165.   linebuffer c;
  166.   int diff;
  167.  
  168.   c=B_current_scr[from];
  169.   for (diff=(from<=to)?1:-1;from!=to;from+=diff)
  170.      B_current_scr[from]=B_current_scr[from+diff];
  171.   if (c.id)
  172.    { B_new_line++;
  173.      c.id=0;
  174.    }
  175.   c.mode=CHANGED;
  176.   B_current_scr[to]=c;
  177. }
  178. /*}}}  */
  179. /*}}}  */
  180.  
  181. /*{{{  B_oputc*/
  182. public void B_oputc(int c)
  183. {
  184.   if (!scr_off)
  185.      if (B_active)
  186.       { if (c=='~' && hz)
  187.          { B_oputc(CTRL_MARK);
  188.            c=HZ_TILDE;
  189.          }
  190.         B_cur_line->code[B_pos.w]=B_code_c_p(c,B_pen);
  191.         B_inc_w_position(B_pos.w);
  192.         B_cur_line->mode=CHANGED;
  193.       }
  194.      else
  195.         oputc(c);
  196. }
  197. /*}}}  */
  198. /*{{{  B_oputs*/
  199. public void B_oputs(unsigned char*s)
  200. {
  201.   if (!scr_off)
  202.      if (B_active)
  203.       { B_cur_line->mode=CHANGED;
  204.         for (;;s++)
  205.          { unsigned char c;
  206.            switch ((c= *s))
  207.             { case '~':
  208.                  if (hz)
  209.                   { B_cur_line->code[B_pos.w]=B_code_c_p(CTRL_MARK,B_pen);
  210.                     B_inc_w_position(B_pos.w);
  211.                     c=HZ_TILDE;
  212.                   }
  213.               default:
  214.                  B_cur_line->code[B_pos.w]=B_code_c_p(c,B_pen);
  215.                  B_inc_w_position(B_pos.w);
  216.                  continue;
  217.               case '\0':
  218.                  break;
  219.             }
  220.            break;
  221.  
  222.          }
  223.       }
  224.      else
  225.         oputs(s);
  226. }
  227. /*}}}  */
  228. /*{{{  B_move_cursor_to*/
  229. public void B_move_cursor_to(int y,int x)
  230. {
  231.   if (!scr_off)
  232.      if (B_active)
  233.       { B_pos.h=y;
  234.         B_pos.w=x;
  235.         B_check_cursor();
  236.       }
  237.      else
  238.         move_cursor_to(y,x);
  239. }
  240. /*}}}  */
  241. /*{{{  B_moveclreol*/
  242. public void B_moveclreol(int y,int x)
  243. {
  244.   if (!scr_off)
  245.      if (B_active)
  246.       { B_move_cursor_to(y,x);
  247.         B_cur_line->mode=CHANGED;
  248.         B_clr(B_cur_line->code,B_pos.w,screen.w);
  249.       }
  250.      else
  251.         moveclreol(y,x);
  252. }
  253. /*}}}  */
  254. /*{{{  B_ClrScr*/
  255. public void B_ClrScr(void)
  256. {
  257.   B_clr_scr_used=True;
  258.   if (!scr_off)
  259.      if (B_active)
  260.       { int l;
  261.  
  262.         for (l=screen.h;l;B_moveclreol(l--,1));
  263.       }
  264.      else
  265.         ClrScr();
  266. }
  267. /*}}}  */
  268. /*{{{  B_insLine*/
  269. public boolean B_insLine(int n)
  270. {
  271.   if (B_active)
  272.    { if (!scr_off)
  273.         while (n-->0)
  274.          { B_al_dl_rotate(screen.h,B_pos.h);
  275.            B_clr(B_current_scr[B_pos.h].code,1,screen.w);
  276.          }
  277.      return(False);
  278.    }
  279.   else
  280.      return(n!=1 || insLine(1));
  281. }
  282. /*}}}  */
  283. /*{{{  B_DelLine*/
  284. public boolean B_DelLine(int n)
  285. {
  286.   if (B_active)
  287.    { if (!scr_off)
  288.         while (n-->0)
  289.          { B_al_dl_rotate(B_pos.h,screen.h);
  290.            B_clr(B_current_scr[screen.h].code,1,screen.w);
  291.          }
  292.      return(False);
  293.    }
  294.   else
  295.      return(n!=1 || DelLine(1));
  296. }
  297. /*}}}  */
  298. /*{{{  B_scroll_region*/
  299. /*{{{  B_rotate*/
  300. private void B_rotate(int y1,int x1,int y2,int x2,boolean up)
  301. {
  302.   int l;
  303.  
  304.   /* no full check for valid edges! */
  305.   if ((l=x2-x1+1))
  306.    { int from,to,diff;
  307.  
  308.      /*{{{  prepare loop variables*/
  309.      if (up)
  310.       { from=y1;to=y2;diff=  1; }
  311.      else
  312.       { from=y2;to=y1;diff= -1; }
  313.      /*}}}  */
  314.      /*{{{  save scrolled out on buffer line*/
  315.      B_copy(B_buff_line,B_current_scr[from].code+x1,l);
  316.      /*}}}  */
  317.      /*{{{  shift up/down*/
  318.      for (;from!=to;from+=diff)
  319.       { B_current_scr[from].mode=CHANGED;
  320.         B_copy
  321.          ( B_current_scr[from].code+x1,
  322.            B_current_scr[from+diff].code+x1,
  323.            l
  324.          );
  325.       }
  326.      /*}}}  */
  327.      /*{{{  put saved text back again*/
  328.      B_current_scr[to].mode=CHANGED;
  329.      B_copy(B_current_scr[from].code+x1,B_buff_line,l);
  330.      /*}}}  */
  331.    }
  332. }
  333. /*}}}  */
  334.  
  335. public boolean B_scroll_region(int y1,int x1,int y2,int x2,boolean up)
  336. {
  337.   if (!scr_off)
  338.      if (B_active)
  339.       /*{{{  scroll in buffer*/
  340.       { B_check_pos(y1,x1);
  341.         B_check_pos(y2,x2);
  342.         /*{{{  maybe change y*/
  343.         if (y1>y2)
  344.          { int l;
  345.  
  346.            l=y1;
  347.            y1=y2;
  348.            y2=l;
  349.          }
  350.         /*}}}  */
  351.         /*{{{  maybe change x*/
  352.         if (x1>x2)
  353.          { int l;
  354.  
  355.            l=x1;
  356.            x1=x2;
  357.            x2=l;
  358.          }
  359.         /*}}}  */
  360.         if (y1!=y2)
  361.          /*{{{  do the scrolling*/
  362.          {
  363.            /*{{{  rotate*/
  364.            if
  365.             (    SCROLL_INVERSE(x2-x1,screen.w)
  366. #           ifdef BLOCK_FLUSH
  367.               && (x1==1 || x2==screen.w)
  368. #           endif
  369.             )
  370.             /*{{{  scroll using al/dl*/
  371.             {
  372.               /*{{{  rotate all lines in region*/
  373.               if (up)
  374.                  B_al_dl_rotate(y1,y2);
  375.               else
  376.                  B_al_dl_rotate(y2,y1);
  377.               /*}}}  */
  378.               /*{{{  maybe rotate remaining screen parts back in buffer!*/
  379.               if (x1!=1)
  380.                  B_rotate(y1,1,y2,x1-1,!up);
  381.               if (x2!=screen.w)
  382.                  B_rotate(y1,x2+1,y2,screen.w,!up);
  383.               /*}}}  */
  384.             }
  385.             /*}}}  */
  386.            else
  387.             /*{{{  scroll in buffer*/
  388.               B_rotate(y1,x1,y2,x2,up);
  389.             /*}}}  */
  390.            /*}}}  */
  391.            /*{{{  clear part of moved line*/
  392.            B_clr(B_current_scr[up?y2:y1].code,x1,x2);
  393.            /*}}}  */
  394.          }
  395.          /*}}}  */
  396.         return(False);
  397.       }
  398.       /*}}}  */
  399.   return(True);
  400. }
  401. /*}}}  */
  402.  
  403. /*{{{  B_invalid*/
  404. public void B_invalid(void)
  405. {
  406.   B_scr_mode=INVALID;
  407. }
  408. /*}}}  */
  409. /*{{{  B_valid*/
  410. public void B_valid(void)
  411. {
  412.   int y;
  413.  
  414.   B_scr_mode=OK;
  415.   B_clr_scr_used=False;
  416.   for (y=screen.h;y;B_current_scr[y--].mode=OK);
  417. }
  418. /*}}}  */
  419. /*{{{  B_oflush*/
  420. /*{{{  cursor_hide/push_position*/
  421. private boolean cursor_hidden=False;
  422. private win_data save_cursor_pos;
  423. /*{{{  csr_push_pos*/
  424. #define csr_push_pos() (save_cursor_pos=B_pos)
  425. /*}}}  */
  426. /*{{{  csr_pop_pos*/
  427. #define csr_pop_pos()                                                   \
  428.    while (scr_pos.w!=save_cursor_pos.w || scr_pos.h!=save_cursor_pos.h) \
  429.     { B_pos=save_cursor_pos;                                            \
  430.       redraw_on_sig=True;                                               \
  431.       S_step_or_move(save_cursor_pos.h,save_cursor_pos.w);              \
  432.       redraw_on_sig=False;                                              \
  433.       break;                                                            \
  434.     }
  435. /*}}}  */
  436. /*{{{  csr_hide*/
  437. #define csr_hide()                                                      \
  438.    while (!cursor_hidden)                                               \
  439.     { cursor_hidden=True;                                               \
  440.       redraw_on_sig=True;                                               \
  441.       scr_cursor(False);                                                \
  442.       redraw_on_sig=False;                                              \
  443.       break;                                                            \
  444.     }
  445. /*}}}  */
  446. /*{{{  csr_no_hide*/
  447. #define csr_no_hide()                                                   \
  448.    while (cursor_hidden)                                                \
  449.     { redraw_on_sig=True;                                               \
  450.       scr_cursor(True);                                                 \
  451.       redraw_on_sig=False;                                              \
  452.       break;                                                            \
  453.     }
  454. /*}}}  */
  455. /*}}}  */
  456. /*{{{  fl_upd_line*/
  457. #ifndef fl_overwrite
  458.   /*{{{  fl_toggle_pen*/
  459.   private void fl_toggle_pen(pentype *p)
  460.   {
  461.     if (sg) S_invalid_pos();
  462.     if (*p==NORM)
  463.      { do_standout();
  464.        *p=HIGHLIGHT;
  465.      }
  466.     else
  467.      { do_standend();
  468.        *p=NORM;
  469.      }
  470.   }
  471.   /*}}}  */
  472. #endif
  473. #ifndef BLOCK_FLUSH
  474.   /*{{{  fl_test_shift*/
  475.   private int fl_test_shift
  476.    ( const c_p_code *left,
  477.      const c_p_code *right,
  478.      const int to,
  479.      const int max
  480.    )
  481.    { int l;
  482.    
  483.      for (left-=(l=1);l<=max;l++,left--)
  484.         if (l)
  485.          { int i;
  486.          
  487.            for (i=l;;i++)
  488.               if (i>to)
  489.                  return(l);
  490.               else if (left[i]!=right[i])
  491.                  break;
  492.          }
  493.      return(0);
  494.    }
  495.   /*}}}  */
  496.   /*{{{  fl_m_insert*/
  497.   private void fl_m_insert(const c_p_code *s, int lg)
  498.    { int l;
  499.      pentype p;
  500.      unsigned char buff[FL_SHIFT_MAX];
  501.    
  502.      for (l=0,p=NORM;lg--;)
  503.       /*{{{  move chars in buffer*/
  504.       { c_p_code c;
  505.  
  506.         c= *s++;
  507.         if (B_get_pen(c)!=p)
  508.          /*{{{  change pen*/
  509.          { if (l)
  510.             /*{{{  print old*/
  511.             { insChar(buff,l);
  512.               S_shift_pos(l);
  513.               l=0;
  514.             }
  515.             /*}}}  */
  516.            fl_toggle_pen(&p);
  517.          }
  518.          /*}}}  */
  519.         /*{{{  store char in buff*/
  520.         buff[l++]=B_get_char(c);
  521.         /*}}}  */
  522.       }
  523.       /*}}}  */
  524.      if (l)
  525.       /*{{{  print missing chars*/
  526.       { insChar(buff,l);
  527.         S_shift_pos(l);
  528.       }
  529.       /*}}}  */
  530.      if (p!=NORM)
  531.         fl_toggle_pen(&p);
  532.    }
  533.   /*}}}  */
  534. #endif
  535. #ifndef fl_overwrite       /* can be defined for special window systems ! */
  536.   /*{{{  fl_overwrite*/
  537.   /*{{{  buffered output for chars*/
  538. #  ifdef BLOCK_FLUSH
  539.      /*{{{  direct print, no buffering*/
  540. #     define over_init()
  541. #     define over_flush()
  542. #     define over_put(c) oputc(c)
  543.      /*}}}  */
  544. #  else
  545.      private int n_buff;
  546.      private unsigned char c_buff;
  547.      private boolean skip_right;
  548.      /*{{{  over_init*/
  549. #     define over_init() (c_buff=skip_right=n_buff=0)
  550.      /*}}}  */
  551.      /*{{{  over_flush*/
  552.      private void over_fl_int(void)
  553.      {
  554.        if (skip_right)
  555.         { step_or_move_cursor(scr_pos.h,scr_pos.w-n_buff,0,skip_right);
  556.           S_shift_pos(n_buff-1);
  557.           skip_right=0;
  558.         }
  559.        skip_right+=moputc(c_buff,n_buff);
  560.        n_buff=0;
  561.      }
  562. #     define over_flush() (n_buff?over_fl_int():(void)0)
  563.      /*}}}  */
  564.      /*{{{  over_skip*/
  565. #     define over_skip(w) (over_flush(),skip_right+=(w))
  566.      /*}}}  */
  567.      /*{{{  over_put*/
  568. #     define over_put(ch) \
  569.        (((ch)==c_buff)?n_buff++:(over_flush(),c_buff=(ch),n_buff=1))
  570.      /*}}}  */
  571. #  endif
  572.   /*}}}  */
  573.  
  574.   private void fl_overwrite
  575.    ( int y,
  576.      int from_txt,
  577.      int to_txt,
  578.      int end_space,
  579.      const c_p_code *cnew
  580. #    ifndef BLOCK_FLUSH
  581.         ,const c_p_code *cold
  582. #    endif
  583.    )
  584.   {
  585.     /*{{{  variables*/
  586.     int x;
  587.     int to_over;
  588.     pentype fl_pen;
  589.     /*}}}  */
  590.  
  591.     over_init();
  592.     /*{{{  maybe disable skiping equal parts*/
  593. #    ifndef BLOCK_FLUSH
  594.       if (to_txt-from_txt<=FL_SHIFT_OVER)
  595.          cold=0;
  596. #    endif
  597.     /*}}}  */
  598.     /*{{{  maybe use clear_to_end_of_line*/
  599.     if (end_space<=to_txt)
  600.        to_over=end_space-1;
  601.     else
  602.      { to_over=to_txt;
  603.        end_space=0;
  604.      }
  605.     /*}}}  */
  606.     S_step_or_move(y,from_txt);
  607.     for (x=from_txt,fl_pen=NORM;x<=to_over;x++)
  608.      /*{{{  print the charater*/
  609.      { int c;
  610.  
  611.        c=cnew[x];
  612.        /*{{{  maybe switch to other pen (sg-chars also switch)*/
  613.        if (B_get_pen(c)!=fl_pen)
  614.         { over_flush();
  615.           fl_toggle_pen(&fl_pen);
  616.         }
  617.        if (B_test_pen(c,SG_SPACE))
  618.         /*{{{  skip the used area, do not print the garbage*/
  619.         { x+=sg-1;
  620.           continue;
  621.         }
  622.         /*}}}  */
  623.        /*}}}  */
  624.        c=B_get_char(c);
  625.        over_put((unsigned char)c);
  626.        S_shift_pos(1);
  627. #      ifndef BLOCK_FLUSH
  628.         /*{{{  check skip over equal parts*/
  629.           if (cold && (mi || fl_pen==NORM))
  630.            { int l;
  631.  
  632.              for (l=x+1;l<=to_over;)
  633.                 if ((c=cnew[l])!=cold[l] || (!mi && !B_test_pen(c,NORM)) )
  634.                    break;
  635.                 else
  636.                    l++;
  637.              l-=x+1;
  638.              if (l>=FL_SHIFT_OVER)
  639.               { x+=l;
  640.                 over_skip(l);
  641.                 continue;
  642.               }
  643.            }
  644.         /*}}}  */
  645. #      endif
  646.      }
  647.      /*}}}  */
  648.     over_flush();
  649.     /*{{{  maybe reset pen*/
  650.     if (fl_pen!=NORM)
  651.        fl_toggle_pen(&fl_pen);
  652.     /*}}}  */
  653.     /*{{{  maybe clear rest of line*/
  654.     if (end_space)
  655.        S_moveclreol(y,end_space);
  656.     /*}}}  */
  657.   }
  658.   /*}}}  */
  659. #else
  660. # include "os_scrbuff.c"
  661. #endif
  662.  
  663. private void fl_upd_line
  664.  ( int y,
  665.    c_p_code * const cold,
  666.    const c_p_code * const cnew,
  667.    boolean full
  668.  )
  669.  {
  670.    /*{{{  variables*/
  671.    int from_txt,to_txt,end_space;
  672. #   ifndef BLOCK_FLUSH
  673.       boolean no_shift;
  674. #   endif
  675.    /*}}}  */
  676.  
  677.    /*{{{  get redraw part of line*/
  678.    /*{{{  init whole line*/
  679.    from_txt=1;
  680.    to_txt=screen.w;
  681.    /*}}}  */
  682.    if (!full)
  683.     /*{{{  try to reduce diff part to a inner block*/
  684.     {
  685.       /*{{{  skip equal part at start*/
  686.       for (;;)
  687.          if (cnew[from_txt]!=cold[from_txt])
  688.             break;
  689.          else if (from_txt==screen.w)
  690.             return;
  691.          else
  692.             from_txt++;
  693.       /*}}}  */
  694.       /*{{{  skip equal part at end*/
  695.       for (;;)
  696.          if (cnew[to_txt]!=cold[to_txt])
  697.              break;
  698.          else
  699.             to_txt--;
  700.       /*}}}  */
  701.     }
  702.     /*}}}  */
  703.    if (am && y==screen.h && to_txt==screen.w)
  704.       to_txt--;
  705.    /*}}}  */
  706.    /*{{{  get whitespace section at end of line*/
  707.    if (ce)
  708.     { for (end_space=screen.w;;)
  709.          if (cnew[end_space]!=SPACE_CODE)
  710.             break;
  711.          else if (--end_space==0)
  712.             break;
  713.       end_space++;
  714.     }
  715.    else
  716.       end_space=screen.w+1;
  717.    /*}}}  */
  718.    /*{{{  check glitches*/
  719. #   ifndef BLOCK_FLUSH
  720.       no_shift=!use_shift || B_scr_mode;
  721. #   endif
  722.    if (!full && B_check_so_glitch)
  723.     { int up;
  724.       int to;
  725.  
  726.       for (up=1,to=screen.w;;)
  727.          if (B_test_pen(cnew[up],NORM) && B_test_pen(cold[up],NORM))
  728.           /*{{{  next char or end search*/
  729.             if (up==to)
  730.                break;
  731.             else
  732.                up++;
  733.           /*}}}  */
  734.          else
  735.           /*{{{  sorry, but must handle the so glitch :-(*/
  736.           { if (xs)
  737.              /*{{{  use clear-to-end-of-line*/
  738.                S_moveclreol(y,1);
  739.              /*}}}  */
  740.             if (xt)
  741.              /*{{{  use al/dl to get rid of the so*/
  742.              { redraw_on_sig=True;
  743.                S_step_or_move(y,1);
  744.                DelLine(1);
  745.                S_step_or_move(y,1);
  746.                insLine(1);
  747.                redraw_on_sig=False;
  748.                B_move_cursor_to(y,1);
  749.                B_DelLine(1);
  750.                B_move_cursor_to(y,1);
  751.                B_insLine(1);
  752.              }
  753.              /*}}}  */
  754.             /*{{{  complete line without shifting*/
  755.             from_txt=1;
  756.             to_txt=screen.w;
  757. #            ifndef BLOCK_FLUSH
  758.                no_shift=True;
  759. #            endif
  760.             /*}}}  */
  761.             break;
  762.           }
  763.           /*}}}  */
  764.     }
  765.    /*}}}  */
  766.    csr_hide();
  767.    /*{{{  update the line*/
  768.    {
  769. #   ifndef BLOCK_FLUSH
  770.      int shift;
  771.  
  772.      /*{{{  get shift width*/
  773.      switch (no_shift)
  774.       { case False:
  775.          { int l1,l2;
  776.  
  777.            l1=to_txt-from_txt;
  778.            l2=(l1+1)/FL_SHIFT_SCALE;
  779.            if (l2)
  780.             { if (l2>FL_SHIFT_MAX)
  781.                  l2=FL_SHIFT_MAX;
  782.               shift=fl_test_shift(cold+from_txt,cnew+from_txt,l1,l2);
  783.               if (shift==0)
  784.                  shift= -fl_test_shift(cnew+from_txt,cold+from_txt,l1,l2);
  785.               break;
  786.             }
  787.          }
  788.         default:
  789.            shift=0;
  790.       }
  791.      /*}}}  */
  792.      redraw_on_sig=True;
  793.      if (shift>0)
  794.       /*{{{  maybe shift right*/
  795.       { if (to_txt<screen.w)
  796.          /*{{{  move and delete*/
  797.          { S_step_or_move(y,to_txt-shift+1);
  798.            delChar(shift);
  799.          }
  800.          /*}}}  */
  801.         S_step_or_move(y,from_txt);
  802.         fl_m_insert(cnew+from_txt,shift);
  803.       }
  804.       /*}}}  */
  805.      else if (shift<0)
  806.       /*{{{  maybe shift left*/
  807.       { S_step_or_move(y,from_txt);
  808.         delChar(-shift);
  809.         if (shift!=-1 || cnew[to_txt]!=SPACE_CODE || to_txt!=end_space)
  810.          /*{{{  insert the chars*/
  811.          { S_step_or_move(y,to_txt+shift+1);
  812.            fl_m_insert(cnew+to_txt+shift+1,-shift);
  813.          }
  814.          /*}}}  */
  815.       }
  816.       /*}}}  */
  817.      else
  818. #   else
  819.         redraw_on_sig=True;
  820. #   endif
  821.         fl_overwrite
  822.          ( y,
  823.            from_txt,
  824.            to_txt,
  825.            end_space,
  826.            cnew
  827. #          ifndef BLOCK_FLUSH
  828.               ,(full && B_scr_mode==OK)?cold:0
  829. #          endif
  830.          );
  831.      redraw_on_sig=False;
  832.      /*{{{  copy new to old*/
  833.      B_copy(cold+from_txt,cnew+from_txt,to_txt-from_txt+1);
  834.      /*}}}  */
  835.    }
  836.    /*}}}  */
  837.  }
  838. /*}}}  */
  839.  
  840. public void B_oflush(void)
  841. {
  842.   if (!scr_off)
  843.    { if (B_active)
  844.       /*{{{  buffer update*/
  845.         do
  846.          {
  847.            /*{{{  variables*/
  848.            linebuffer *new;
  849.            linebuffer *old;
  850.            /*}}}  */
  851.  
  852.            csr_push_pos();
  853.            /*{{{  maybe handle signal flush*/
  854.            if (interrupt_restore)
  855.             { B_clr_scr_used=True;
  856.               interrupt_restore=False;
  857.             }
  858.            /*}}}  */
  859.            /*{{{  set new/old to both buffers and change buffers*/
  860.            new=B_current_scr;
  861.            B_toggle_start();
  862.            old=B_current_scr;
  863.            B_update_line_pointer();
  864.            /*}}}  */
  865.            /*{{{  check invalid screen/dl_al usage*/
  866.            if (B_clr_scr_used)
  867.               B_scr_mode=INVALID;
  868.            else if (B_use_dl_al)
  869.               if (FL_NO_DL_AL(B_new_line,screen.h))
  870.                  B_use_dl_al=False;
  871.               else if (B_scr_mode!=OK)
  872.                  B_use_dl_al=False;
  873.            /*}}}  */
  874.            /*{{{  maybe do clrscr first!*/
  875.            if (B_clr_scr_used)
  876.             { csr_hide();
  877.               redraw_on_sig=True;
  878.               S_ClrScr();
  879.               redraw_on_sig=False;
  880.               B_clr_scr_used=False;
  881.             }
  882.            /*}}}  */
  883.            /*{{{  update lines*/
  884.            { int first_diff;
  885.              int first_upd;
  886.              boolean d,a;
  887.              int m_add;
  888.  
  889.              for
  890.               ( m_add=1,
  891.                 first_upd=1,
  892.                 a=d=B_use_dl_al,
  893.                 first_diff=1+(B_use_dl_al ? 0 : screen.h)
  894.               ; first_upd<=screen.h && !interrupt_restore
  895.               ;
  896.               )
  897.               {
  898.                 /*{{{  update all correct scrolled lines*/
  899.                 { linebuffer *op,*np;
  900.  
  901.                   for
  902.                    ( op=old+first_upd,np=new+first_upd
  903.                    ; first_upd<first_diff
  904.                    ; op++,np++,first_upd++
  905.                    )
  906.                    { if
  907.                       (    np->mode!=OK
  908.                         || np->id!=op->id
  909.                         || B_scr_mode!=OK
  910.                       )
  911.                         fl_upd_line
  912.                          ( first_upd,
  913.                            op->code,
  914.                            np->code,
  915.                            B_scr_mode!=OK
  916.                          );
  917.                      op->mode=OK;
  918.                      op->id=np->id=first_upd;
  919.                    }
  920.                 }
  921.                 /*}}}  */
  922.                 /*{{{  try to delete a line*/
  923.                 if (d)
  924.                  { int yo,yn;
  925.  
  926.                    for (yn=yo=first_diff,d=False;yn<=screen.h;)
  927.                     { int idn;
  928.  
  929.                       if (old[yo].id==(idn=new[yn].id))
  930.                        /*{{{  next(new,old), maybe inc correct shifted part*/
  931.                        { if (yo==first_diff && yn==first_diff)
  932.                             first_diff++;
  933.                          yo+=1;
  934.                          yn+=1;
  935.                        }
  936.                        /*}}}  */
  937.                       else if (idn==0)
  938.                        /*{{{  next new*/
  939.                          yn++;
  940.                        /*}}}  */
  941.                       else
  942.                        /*{{{  do a dl*/
  943.                        { int n;
  944.  
  945.                          /*{{{  get number of delete lines*/
  946.                          { int ido;
  947.                            int ys;
  948.  
  949.                            for
  950.                             ( n=1
  951.                             ; (ys=yo+n)<=screen.h && (ido=old[ys].id) && ido!=idn
  952.                             ; n++
  953.                             );
  954.                            if (n>FL_MAX_AL_DL)
  955.                               n=FL_MAX_AL_DL;
  956.                            m_add+=n-1;
  957.                          }
  958.                          /*}}}  */
  959.                          csr_hide();
  960.                          redraw_on_sig=True;
  961.                          S_step_or_move(yo,1);
  962.                          DelLine(n);
  963.                          redraw_on_sig=False;
  964.                          B_move_cursor_to(yo,1);
  965.                          while (n--)
  966.                             B_DelLine(1);
  967.                          d=True;
  968.                          break;
  969.                        }
  970.                        /*}}}  */
  971.                     }
  972.                    /*{{{  no more deletes, so adds are allowed unlimited*/
  973.                    if (!d)
  974.                       m_add=screen.h;
  975.                    /*}}}  */
  976.                  }
  977.                 /*}}}  */
  978.                 /*{{{  try to add a line*/
  979.                 if (a)
  980.                  { int yo,yn;
  981.  
  982.                    for (yo=yn=first_diff,a=False;yo<=screen.h;)
  983.                     { int ido,idn;
  984.  
  985.                       if ((ido=old[yo].id)==(idn=new[yn].id))
  986.                        /*{{{  next(new,old), maybe inc correct shifted part*/
  987.                        { if (yo==first_diff && yn==first_diff)
  988.                             first_diff++;
  989.                          yo+=1;
  990.                          yn+=1;
  991.                        }
  992.                        /*}}}  */
  993.                       else if (ido<idn)
  994.                        /*{{{  next old*/
  995.                          yo++;
  996.                        /*}}}  */
  997.                       else
  998.                        /*{{{  do a al*/
  999.                        { int n;
  1000.  
  1001.                          /*{{{  get number of add lines*/
  1002.                          { int ys;
  1003.  
  1004.                            for (n=1;(ys=yn+n)<=screen.h && new[ys].id==0;n++);
  1005.                            /*{{{  limit #, to prevent scroll out*/
  1006.                            if (n>m_add)
  1007.                             { n=m_add;
  1008.                               m_add=0;
  1009.                             }
  1010.                            else
  1011.                               m_add-=n;
  1012.                            /*}}}  */
  1013.                          }
  1014.                          /*}}}  */
  1015.                          csr_hide();
  1016.                          redraw_on_sig=True;
  1017.                          S_step_or_move(yo,1);
  1018.                          insLine(n);
  1019.                          redraw_on_sig=False;
  1020.                          B_move_cursor_to(yo,1);
  1021.                          while (n--)
  1022.                             B_insLine(1);
  1023.                          a=True;
  1024.                          break;
  1025.                        }
  1026.                        /*}}}  */
  1027.                     }
  1028.                  }
  1029.                 /*}}}  */
  1030.               }
  1031.            }
  1032.            /*}}}  */
  1033.            /*{{{  restore and show cursor*/
  1034.            csr_pop_pos();
  1035.            csr_no_hide();
  1036.            /*}}}  */
  1037.            /*{{{  screen is now up to date*/
  1038.            B_scr_mode=OK;
  1039.            B_use_dl_al=al&&dl;
  1040.            B_new_line=0;
  1041.            /*}}}  */
  1042.          }
  1043.         while (interrupt_restore);
  1044.       /*}}}  */
  1045.      oflush;
  1046.    }
  1047. }
  1048. /*}}}  */
  1049.  
  1050. /*{{{  B_do_standout/end*/
  1051. /*{{{  B_sg*/
  1052. private void B_sg(int i,c_p_code c)
  1053. {
  1054.   do
  1055.    { B_cur_line->code[B_pos.w]=c;
  1056.      B_inc_w_position(B_pos.w);
  1057.    }
  1058.   while (--i);
  1059. }
  1060. /*}}}  */
  1061. /*{{{  B_do_standout*/
  1062. public void B_do_standout(void)
  1063. {
  1064.   if (so)
  1065.    { B_pen=HIGHLIGHT;
  1066.      if (B_active)
  1067.       { if (sg)
  1068.            B_sg(sg,SO_CODE);
  1069.       }
  1070.      else
  1071.         do_standout();
  1072.    }
  1073. }
  1074. /*}}}  */
  1075. /*{{{  B_do_standend*/
  1076. public void B_do_standend(void)
  1077. {
  1078.   if (so)
  1079.    { B_pen=NORM;
  1080.      if (B_active)
  1081.       { if (sg)
  1082.            B_sg(sg,SE_CODE);
  1083.       }
  1084.      else
  1085.         do_standend();
  1086.    }
  1087. }
  1088. /*}}}  */
  1089. /*}}}  */
  1090. /*{{{  B_init_terminal*/
  1091. public void B_init_terminal(void)
  1092. {
  1093.   init_terminal();
  1094.   S_invalid_pos();
  1095.   B_do_buffer=True;
  1096.   B_scr_mode=INVALID;
  1097.   B_clr_scr_used=True;
  1098.   B_check_active();
  1099. }
  1100. /*}}}  */
  1101. /*{{{  B_reset_terminal*/
  1102. public void B_reset_terminal(void)
  1103. {
  1104.   B_oflush();
  1105.   S_invalid_pos();
  1106.   reset_terminal();
  1107.   B_do_buffer=False;
  1108.   B_check_active();
  1109. }
  1110. /*}}}  */
  1111.  
  1112. /*{{{  B_get_terminal_capability*/
  1113. public int B_get_terminal_capability(void)
  1114. {
  1115.   int x;
  1116.   win_data old_screen;
  1117.  
  1118.   /*{{{  get old size of the screen, or dummy value*/
  1119.   if (B_scr_data && B_do_buffer)
  1120.      old_screen=screen;
  1121.   else
  1122.      old_screen.h= -1;
  1123.   /*}}}  */
  1124.   if ((x=get_terminal_capability()))
  1125.      return(x);
  1126.   if ((old_screen.h!=screen.h) || (old_screen.w!=screen.w))
  1127.    /*{{{  changed sizes, so new buffer*/
  1128.    { if (B_scr_data)
  1129.         paket_free(B_scr_data);
  1130.      if
  1131.       /*{{{  can malloc space for 2 buffers*/
  1132.       ((B_scr_data=
  1133.            paket_malloc
  1134.             (   2*screen.w*sizeof(c_p_code)    /* empty and buffer line */
  1135.               +   2 * screen.h                 /* 2 buffer: */
  1136.                 * (  sizeof(linebuffer)           /* line descriptor */
  1137.                    + screen.w*sizeof(c_p_code)    /* text field */
  1138.                   )
  1139.              )
  1140.       ))
  1141.       /*}}}  */
  1142.       /*{{{  start up buffering*/
  1143.       { B_get_start(B_buf_id=False);
  1144.         /*{{{  init empty and buff line*/
  1145.         B_empty_line=(c_p_code*)((linebuffer*)B_scr_data+2*screen.h);
  1146.         for
  1147.          ( B_buff_line=B_empty_line,x=screen.w
  1148.          ; x--
  1149.          ; *B_buff_line++=SPACE_CODE
  1150.          );
  1151.         /*}}}  */
  1152.         /*{{{  set up each line buffer*/
  1153.         { c_p_code *s;
  1154.           linebuffer *l;
  1155.  
  1156.           for
  1157.            ( l=B_scr_data,x=2*screen.h,s=B_buff_line+screen.w
  1158.            ; x
  1159.            ; x--,l++,s+=screen.w
  1160.            )
  1161.            { l->mode=OK;
  1162.              if ((l->id=(l-B_scr_data+1))>screen.h)
  1163.                 l->id-=screen.h;
  1164.              B_clr(l->code=s-1,1,screen.w);
  1165.            }
  1166.         }
  1167.         /*}}}  */
  1168.         /*{{{  empty screen, cursor at 1/1*/
  1169.         B_move_cursor_to(1,1);
  1170.         S_ClrScr();
  1171.         B_valid();
  1172.         B_use_dl_al=al&&dl;
  1173.         B_new_line=0;
  1174.         /*}}}  */
  1175.       }
  1176.       /*}}}  */
  1177.    }
  1178.    /*}}}  */
  1179.   B_check_active();
  1180.   if (B_scr_data)
  1181.    { if ((xs && !ce) || (xt && !B_use_dl_al))
  1182.       { so=0;
  1183.         allow_text_so=False;
  1184.         if (dsp.ctrl==ictrl_dsp)
  1185.          { dsp.ctrl=mark_dsp;
  1186.            dsp.ctrl_add=0;
  1187.          }
  1188.       }
  1189.      B_check_so_glitch=(so && (sg || xs || xt));
  1190.    }
  1191.   return(0);
  1192. }
  1193. /*}}}  */
  1194.  
  1195. #ifdef EXT_SCRBUFF_ACCESS
  1196.    /*{{{  cur_scr_char*/
  1197.    public unsigned char cur_scr_char(int y,int x)
  1198.    {
  1199.      return
  1200.       ( (B_active && x<=screen.w && x>0 && y<=screen.h && y>0)
  1201.          ? (unsigned char)B_get_char(B_current_scr[y].code[x])
  1202.          : (unsigned char)'\0'
  1203.       );
  1204.    }
  1205.    /*}}}  */
  1206. #endif
  1207.